home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PRINTER / JPSRC11.ARJ / JETBMP.C next >
C/C++ Source or Header  |  1991-08-04  |  37KB  |  1,140 lines

  1. /*
  2.  *      JET PAK - HP DeskJet and LaserJet series printer utilities
  3.  *
  4.  *      JETBMP module - bitmap utility functions
  5.  *
  6.  *      Version 1.1 (Public Domain)
  7.  */
  8.  
  9. /* system include files */
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <string.h>
  13.  
  14. /* application include files */
  15. #include "jetfont.h"
  16. #include "jetutil.h"
  17.  
  18. /*
  19.  * MODULE GLOBAL DATA
  20.  */
  21.  
  22. /* bitmap outline edge information, including slope type */
  23. #define SLOPE_NONE      0
  24. #define SLOPE_NE        1
  25. #define SLOPE_SE        2
  26. #define SLOPE_SW        3
  27. #define SLOPE_NW        4
  28. typedef struct edge {
  29.     struct edge *nextedge;
  30.     UNSIGNEDINT sx;
  31.     UNSIGNEDINT sy;
  32.     SIGNEDINT dx;
  33.     SIGNEDINT dy;
  34.     UNSIGNEDBYTE slope;
  35. } EDGE;
  36.  
  37. /* bitmap outline polygon - series of edges forming closed polygon */
  38. typedef struct poly {
  39.     struct poly *nextpoly;
  40.     struct edge *firstedge;
  41. } POLY;
  42.  
  43. /* lists of edges collected in first phase (four types) */
  44. static EDGE *top_edges[MAX_CELL_HEIGHT] = { 0 };
  45. static EDGE *right_edges[MAX_CELL_WIDTH] = { 0 };
  46. static EDGE *bottom_edges[MAX_CELL_HEIGHT] = { 0 };
  47. static EDGE *left_edges[MAX_CELL_WIDTH] = { 0 };
  48.  
  49. static UNSIGNEDBYTE bits[8] =
  50. {
  51.     0x80, 0x40, 0x20, 0x10,
  52.     0x08, 0x04, 0x02, 0x01,
  53. };
  54.  
  55. /*
  56.  * BITMAP SMOOTHING MACROS AND FUNCTIONS
  57.  */
  58.  
  59. /* set a single bit */
  60. #define bitset(p,w,h,x,y)                                           \
  61.     {                                                               \
  62.         if ((x) < (w) && (y) < (h))                                 \
  63.         *((p) + (y)*(((w) + 7)/8) + (x)/8) |= bits[(x)%8];          \
  64.     }
  65.  
  66. /* clear a single bit */
  67. #define bitclear(p,w,h,x,y)                                         \
  68.     {                                                               \
  69.         if ((x) < (w) && (y) < (h))                                 \
  70.             *((p) + (y)*(((w) + 7)/8) + (x)/8) &= ~bits[(x)%8];     \
  71.     }
  72.  
  73. /* test a single bit */
  74. #define bitat(p,w,h,x,y)                                            \
  75.     (    (x) < (w)                                                  \
  76.       && (y) < (h)                                                  \
  77.       && (*((p) + (y)*(((w) + 7)/8) + (x)/8) & bits[(x)%8]) != 0    \
  78.     )
  79.  
  80. static void bitmapclear(p,w,h)
  81. UNSIGNEDBYTE *p;    /* pointer to LJ format bitmap to be cleared */
  82. UNSIGNEDINT w, h;   /* dimensions of bitmap */
  83. {
  84.     /*
  85.      * Clear the w by h bit bitmap at *p
  86.      */
  87.     UNSIGNEDINT wb = (w + 7)/8;
  88.  
  89.     while (h-- > 0)
  90.         for (w = 0; w < wb; w++)
  91.             *p++ = 0;
  92. }
  93.  
  94. static void edge_smooth(p, w, h, ep, slope, cut)
  95. UNSIGNEDBYTE *p;    /* pointer to LJ format bitmap */
  96. UNSIGNEDINT w, h;   /* dimensions of LJ bitmap in dots */
  97. EDGE *ep;           /* pointer to edge position and direction */
  98. UNSIGNEDBYTE slope; /* type of slope to be applied to edge */
  99. SIGNEDINT cut;      /* where to start cutting into the edge */
  100. {
  101.     /*
  102.      * Smooth a single edge within bitmap.
  103.      */
  104.     UNSIGNEDINT x, y;
  105.  
  106.     switch(slope)
  107.     {
  108.     case SLOPE_NE:
  109.         if (cut >= 0)
  110.             return;
  111.         if (cut < ep->dy)
  112.             cut = ep->dy;
  113.         x = ep->sx;
  114.         for (y = ep->sy + ep->dy - cut; y > ep->sy + ep->dy; y--)
  115.             bitset(p, w, h, x, y-1);
  116.         break;
  117.     case SLOPE_SE:
  118.         if (cut <= 0)
  119.             return;
  120.         if (cut > ep->dy)
  121.             cut = ep->dy;
  122.         x = ep->sx - 1;
  123.         for (y = ep->sy + cut; y < ep->sy + ep->dy; y++)
  124.             bitset(p, w, h, x, y);
  125.         break;
  126.     case SLOPE_SW:
  127.         if (cut <= 0)
  128.             return;
  129.         if (cut > ep->dy)
  130.             cut = ep->dy;
  131.         x = ep->sx - 1;
  132.         for (y = ep->sy; y < ep->sy + ep->dy - cut; y++)
  133.             bitset(p, w, h, x, y);
  134.         break;
  135.     case SLOPE_NW:
  136.         if (cut >= 0)
  137.             return;
  138.         if (cut < ep->dy)
  139.             cut = ep->dy;
  140.         x = ep->sx;
  141.         for (y = ep->sy; y > ep->sy + cut; y--)
  142.             bitset(p, w, h, x, y-1);
  143.         break;
  144.     }
  145. }
  146.  
  147. static void bitmap_free_all(firstpoly, cw, ch)
  148. POLY *firstpoly;    /* handle to bitmap outline tree data */
  149. UNSIGNEDINT cw, ch; /* dimensions of LJ bitmap in dots */
  150. {
  151.     /*
  152.      * Free up all the heap storage allocated during the bitmap
  153.      * smoothing process.
  154.      */
  155.     POLY *pp;
  156.     EDGE *ep;
  157.     UNSIGNEDINT x, y;
  158.  
  159.     /* free edge lists */
  160.     for (x = 0; x < cw; x++)
  161.     {
  162.         while ((ep = left_edges[x]) != NULL)
  163.         {
  164.             left_edges[x] = ep->nextedge;
  165.             free(ep);
  166.         }
  167.  
  168.         while ((ep = right_edges[x]) != NULL)
  169.         {
  170.             right_edges[x] = ep->nextedge;
  171.             free(ep);
  172.         }
  173.     }
  174.     for (y = 0; y < ch; y++)
  175.     {
  176.         while ((ep = top_edges[y]) != NULL)
  177.         {
  178.             top_edges[y] = ep->nextedge;
  179.             free(ep);
  180.         }
  181.  
  182.         while ((ep = bottom_edges[y]) != NULL)
  183.         {
  184.             bottom_edges[y] = ep->nextedge;
  185.             free(ep);
  186.         }
  187.     }
  188.  
  189.     /* free outline trees */
  190.     while ((pp = firstpoly) != NULL)
  191.     {
  192.         while ((ep = pp->firstedge) != NULL)
  193.         {
  194.             pp->firstedge = ep->nextedge;
  195.             free(ep);
  196.         }
  197.  
  198.         firstpoly = pp->nextpoly;
  199.         free(pp);
  200.     }
  201. }
  202.  
  203. static int bitmap_trace(sbp, bmp, cw, ch)
  204. UNSIGNEDBYTE *sbp;  /* pointer to source (LJ) bitmap */
  205. UNSIGNEDBYTE *bmp;  /* pointer to smoothed bitmap mask */
  206. UNSIGNEDINT cw, ch; /* dimensions of LJ bitmap in dots */
  207. {
  208.     /*
  209.      * Find the edges within a bitmap, by scanning adjacent rows and
  210.      * columns. Four types of edges are identified - top, bottom, right
  211.      * and left.
  212.      *
  213.      * The boundary cases where a row or column being examined lies
  214.      * outside the regular bitmap are handled by pointing to the
  215.      * smoothed bitmap mask (known to be all zero at this point).
  216.      *
  217.      * The meaning of the variables is as follows:
  218.      *
  219.      * x, y:    tracks the dot being examined
  220.      * bp1:     points to the byte containing the first row/column
  221.      * bp2:     points to the byte containing the second row/column
  222.      * mask1:   mask for the first row/column (used with bp1)
  223.      * mask2:   mask for the second row/column (used with bp2)
  224.      * offset:  byte offset between bitmap rows
  225.      */
  226.     EDGE **epp, *ep;
  227.     UNSIGNEDINT x, y, mask1, mask2, offset;
  228.     UNSIGNEDBYTE *bp1, *bp2;
  229.  
  230.     /* get bitmap derived data used in subsequent calculations */
  231.     offset = (cw + 7)/8;
  232.  
  233.     /* collect top edges */
  234.     bp1 = bmp;  /* first row lies above real bitmap */
  235.     bp2 = sbp;
  236.     for (y = 0; y < ch; y++)
  237.     {
  238.         epp = &top_edges[y];
  239.  
  240.         for (x = 0, mask1 = 0x80; x < cw; )
  241.         {
  242.             if (    ((*bp1 & mask1) == 0)
  243.                  && ((*bp2 & mask1) != 0) )
  244.             {
  245.                 *epp = ep = (EDGE *)zalloc(sizeof(EDGE));
  246.                 if (ep == NULL)
  247.                 {
  248.                     bitmap_free_all(NULL, cw, ch);
  249.                     return(ERROR);
  250.                 }
  251.                 ep->sx = x;
  252.                 ep->sy = y;
  253.  
  254.                 do {
  255.                     ep->dx++;
  256.                     x++;
  257.                     if ((mask1 >>= 1) == 0)
  258.                     {
  259.                         mask1 = 0x80;
  260.                         bp1++;
  261.                         bp2++;
  262.                     }
  263.                 } while (    (x < cw)
  264.                           && ((*bp1 & mask1) == 0)
  265.                           && ((*bp2 & mask1) != 0) );
  266.  
  267.                 epp = &ep->nextedge;
  268.             }
  269.             else
  270.             {
  271.                 x++;
  272.                 if ((mask1 >>= 1) == 0)
  273.                 {
  274.                     mask1 = 0x80;
  275.                     bp1++;
  276.                     bp2++;
  277.                 }
  278.             }
  279.         }
  280.  
  281.         if (mask1 != 0x80)
  282.         {
  283.             /* bitmap width not an exact multiple of 8 */
  284.             bp1++;
  285.             bp2++;
  286.         }
  287.  
  288.         if (y == 0)
  289.             bp1 = sbp;
  290.  
  291.     }
  292.  
  293.     /* collect bottom edges */
  294.     bp1 = sbp;
  295.     bp2 = sbp + offset;
  296.     for (y = 0; y < ch; y++)
  297.     {
  298.         if (y == (ch - 1))
  299.             bp2 = bmp;  /* second row lies below real bitmap */
  300.  
  301.         epp = &bottom_edges[y];
  302.  
  303.         for (x = 0, mask1 = 0x80; x < cw; )
  304.         {
  305.             if (    ((*bp1 & mask1) != 0)
  306.                  && ((*bp2 & mask1) == 0) )
  307.             {
  308.                 *epp = ep = (EDGE *)zalloc(sizeof(EDGE));
  309.                 if (ep == NULL)
  310.                 {
  311.                     bitmap_free_all(NULL, cw, ch);
  312.                     return(ERROR);
  313.                 }
  314.                 do {
  315.                     ep->dx--;
  316.                     x++;
  317.                     if ((mask1 >>= 1) == 0)
  318.                     {
  319.                         mask1 = 0x80;
  320.                         bp1++;
  321.                         bp2++;
  322.                     }
  323.                 } while (    (x < cw)
  324.                           && ((*bp1 & mask1) != 0)
  325.                           && ((*bp2 & mask1) == 0) );
  326.  
  327.                 ep->sx = x;
  328.                 ep->sy = y + 1;
  329.  
  330.                 epp = &ep->nextedge;
  331.             }
  332.             else
  333.             {
  334.                 x++;
  335.                 if ((mask1 >>= 1) == 0)
  336.                 {
  337.                     mask1 = 0x80;
  338.                     bp1++;
  339.                     bp2++;
  340.                 }
  341.             }
  342.         }
  343.  
  344.         if (mask1 != 0x80)
  345.         {
  346.             /* bitmap width not an exact multiple of 8 */
  347.             bp1++;
  348.             bp2++;
  349.         }
  350.     }
  351.  
  352.     /* collect right edges */
  353.     mask1 = 0x80;
  354.     mask2 = 0x40;
  355.     for (x = 0; x < cw; x++)
  356.     {
  357.         bp1 = sbp + x/8;
  358.         if (x == (cw - 1))
  359.             bp2 = bmp; /* second row lies to the right of real bitmap */
  360.         else
  361.             bp2 = sbp + (x + 1)/8;
  362.  
  363.         epp = &right_edges[x];
  364.  
  365.         for (y = 0; y < ch; )
  366.         {
  367.             if (    ((*bp1 & mask1) != 0)
  368.                  && ((*bp2 & mask2) == 0) )
  369.             {
  370.                 *epp = ep = (EDGE *)zalloc(sizeof(EDGE));
  371.                 if (ep == NULL)
  372.                 {
  373.                     bitmap_free_all(NULL, cw, ch);
  374.                     return(ERROR);
  375.                 }
  376.                 ep->sx = x + 1;
  377.                 ep->sy = y;
  378.  
  379.                 do {
  380.                     ep->dy++;
  381.                     y++;
  382.                     bp1 += offset;
  383.                     bp2 += offset;
  384.                 } while (    (y < ch)
  385.                           && ((*bp1 & mask1) != 0)
  386.                           && ((*bp2 & mask2) == 0) );
  387.  
  388.                 epp = &ep->nextedge;
  389.             }
  390.             else
  391.             {
  392.                 y++;
  393.                 bp1 += offset;
  394.                 bp2 += offset;
  395.             }
  396.         }
  397.  
  398.         mask1 = mask2;
  399.         if ((mask2 >>= 1) == 0)
  400.             mask2 = 0x80;
  401.     }
  402.  
  403.     /* collect left edges */
  404.     mask1 = 0x01;
  405.     mask2 = 0x80;
  406.     for (x = 0; x < cw; x++)
  407.     {
  408.         if (x == 0)
  409.             bp1 = bmp; /* first row lies to the left of real bitmap */
  410.         else
  411.             bp1 = sbp + (x - 1)/8;
  412.         bp2 = sbp + x/8;
  413.  
  414.         epp = &left_edges[x];
  415.  
  416.         for (y = 0; y < ch; )
  417.         {
  418.             if (    ((*bp1 & mask1) == 0)
  419.                  && ((*bp2 & mask2) != 0) )
  420.             {
  421.                 *epp = ep = (EDGE *)zalloc(sizeof(EDGE));
  422.                 if (ep == NULL)
  423.                 {
  424.                     bitmap_free_all(NULL, cw, ch);
  425.                     return(ERROR);
  426.                 }
  427.  
  428.                 do {
  429.                     ep->dy--;
  430.                     y++;
  431.                     bp1 += offset;
  432.                     bp2 += offset;
  433.                 } while (    (y < ch)
  434.                           && ((*bp1 & mask1) == 0)
  435.                           && ((*bp2 & mask2) != 0) );
  436.  
  437.                 ep->sx = x;
  438.                 ep->sy = y;
  439.  
  440.                 epp = &ep->nextedge;
  441.             }
  442.             else
  443.             {
  444.                 y++;
  445.                 bp1 += offset;
  446.                 bp2 += offset;
  447.             }
  448.         }
  449.  
  450.         mask1 = mask2;
  451.         if ((mask2 >>= 1) == 0)
  452.             mask2 = 0x80;
  453.     }
  454.  
  455.     return(OK);
  456. }
  457.  
  458. int bitmap_smooth(sbp, bmp, cw, ch)
  459. UNSIGNEDBYTE *sbp;  /* pointer to source (LJ) bitmap */
  460. UNSIGNEDBYTE *bmp;  /* pointer to smoothed bitmap mask */
  461. UNSIGNEDINT cw, ch; /* dimensions of LJ bitmap in dots */
  462. {
  463.     /*
  464.      * Create smoothing data for a LaserJet bitmap. This is done
  465.      * by filling in a mask bitmap of the same dimensions as the
  466.      * source bitmap.
  467.      *
  468.      * A clear bit in the mask indicates the LaserJet bit should be
  469.      * to the left in the DeskJet bitmap; a set bit in the mask indicates
  470.      * the LaserJet bit should be to the right in the DeskJet bitmap.
  471.      *
  472.      * The LaserJet bitmap may itself be modified: it is sometimes
  473.      * necessary to clear two adjacent bits within the body of a
  474.      * character.
  475.      *
  476.      * The procedure for creating the smoothed bitmap mask is as
  477.      * follows:
  478.      *
  479.      * 1. The LJ bitmap is examined (by bitmap_trace()) to find the
  480.      *    edge information. This is saved in four arrays (indexed by
  481.      *    row or column) of pointers to linked lists of edges:
  482.      *
  483.      *      EDGE top_edges[]
  484.      *      EDGE right_edges[]
  485.      *      EDGE bottom_edges[]
  486.      *      EDGE left_edges[]
  487.      *
  488.      *    EDGEs are expressed as a start position and an offset, with
  489.      *    the convention that top edges point to the right, right edges
  490.      *    point downwards, bottom edges point to the left and left
  491.      *    edges point upwards, thus:
  492.      *
  493.      *      ^---->
  494.      *      |@@@@|
  495.      *      |@@@@|
  496.      *      |@@@@|
  497.      *      <----V
  498.      *
  499.      * 2. The edges are then joined up, in sequence, into polygons.
  500.      *    A linked list of POLYGON structures is constructed; each
  501.      *    POLYGON points to a ring of EDGE structures (the first EDGE
  502.      *    is pointed at by the POLYGON and also by the last EDGE in
  503.      *    the ring).
  504.      *
  505.      *    As EDGEs are assigned to a place in a POLYGON they are
  506.      *    removed from the EDGE array linked lists, so that eventually,
  507.      *    the EDGE array linked lists should be left empty.
  508.      *
  509.      * 3. A pass is made round the EDGES of each POLYGON to determine
  510.      *    the type of slope associated with left and right edges that
  511.      *    are separated by two 1 bit wide edges of the same type (the
  512.      *    only edges of concern during the smoothing process)
  513.      *
  514.      *      |@@@  @@@|    @|        |@
  515.      *      |@@@  @@@|    @|        |@
  516.      *      |@@@  @@@|    @|        |@
  517.      *      <^@@  @@<V    @V>      ^>@
  518.      *       |@@  @@|     @@|      |@@
  519.      *       |@@  @@|     @@|      |@@
  520.      *       <^@  @<V     @@V>    ^>@@
  521.      *        |@  @|      @@@|    |@@@
  522.      *        |@  @|      @@@|    |@@@
  523.      *        |@  @|      @@@|    |@@@
  524.      *
  525.      *      NW      SW     SE      NE
  526.      *
  527.      *    The type of slope is recorded in the EDGE structure.
  528.      *
  529.      * 4. Another pass is made round the EDGES of each POLYGON to
  530.      *    actually apply the slope and create the smoothed bitmap mask.
  531.      *    This involves not only applying the slope identified in step
  532.      *    3, but also extending that slope to adjacent left and
  533.      *    right edges that don't have a slope identified.
  534.      *
  535.      *    edge_smooth() is called to apply smoothing to a single
  536.      *    edge at a defined position. This sets bits in the smoothed
  537.      *    bitmap mask when the ideal position of a bit at the edge
  538.      *    of the character lies to the right, rather than the left.
  539.      *
  540.      * 5. The smoothed bitmap mask is now completed by scanning
  541.      *    each row of the bitmap. The source bitmap and the smoothed
  542.      *    mask bitmap are considered together to envisage what the
  543.      *    output DeskJet bitmap will look like.
  544.      *
  545.      *    Adjacent set bits in the DeskJet bitmap are not allowed.
  546.      *    So if a bit at a left edge needs to be to the right, bits
  547.      *    in the body of a character are flipped over to the right,
  548.      *    one by one.
  549.      *
  550.      *    If adjacent set bits wind up at the right edge, and the
  551.      *    right edge bit ideally should be on the left, two adjacent
  552.      *    clear bits are created in the body of the character to
  553.      *    allow this.
  554.      *
  555.      *    As a special case of the above: if the character has no body
  556.      *    (i.e. the bit on the left edge is adjacent to the bit on the
  557.      *    right edge), the bit on the left edge is shifted back to the
  558.      *    left. This is the only case where a bit cannot be placed at
  559.      *    its "ideal" position in the output DeskJet bitmap.
  560.      */
  561.     EDGE **pepp, **epp, *ep, *epm2, *epm1, *epp1, *epp2, *sep;
  562.     POLY **ppp, *pp, *firstpoly = NULL;
  563.     UNSIGNEDINT x, y;
  564.     struct edge *null_nep = NULL;
  565.  
  566.     /* clear the mask bitmap */
  567.     bitmapclear(bmp, cw, ch);
  568.  
  569.     /* 1. trace the edges of the shapes in the bitmap */
  570.     if (bitmap_trace(sbp, bmp, cw, ch) == ERROR)
  571.         return(ERROR);
  572.  
  573.     /* 2. join edges into polygons */
  574.     ppp = &firstpoly;
  575.     for (x = 0; x < cw; x++)
  576.     {
  577.         while (*(epp = &left_edges[x]) != NULL)
  578.         {
  579.             /* unused edge - make first of polygon */
  580.             *ppp = (POLY *)zalloc(sizeof(POLY));
  581.             if (*ppp == NULL)
  582.             {
  583.                 bitmap_free_all(firstpoly, cw, ch);
  584.                 return(ERROR);
  585.             }
  586.  
  587.             pepp = &(*ppp)->firstedge;
  588.             do {
  589.                 /* move found edge from line list to polygon list */
  590.                 *pepp = *epp;
  591.                 *epp = (*epp)->nextedge;
  592.  
  593.                 /* search for next edge in polygon */
  594.                 if ((*pepp)->dx == 0)
  595.                 {
  596.                     /* search top and bottom lists */
  597.                     if (((*pepp)->sy+(*pepp)->dy) < ch)
  598.                     {
  599.                         epp = &top_edges[(*pepp)->sy+(*pepp)->dy];
  600.  
  601.                         while (*epp != NULL && (*epp)->sx != (*pepp)->sx)
  602.                             epp = &(*epp)->nextedge;
  603.                     }
  604.                     else
  605.                     {
  606.                         epp = &null_nep;
  607.                     }
  608.  
  609.                     if (*epp == NULL && ((*pepp)->sy+(*pepp)->dy) != 0)
  610.                     {
  611.                         epp = &bottom_edges[(*pepp)->sy+(*pepp)->dy-1];
  612.                         while (*epp != NULL && (*epp)->sx != (*pepp)->sx)
  613.                             epp = &(*epp)->nextedge;
  614.                     }
  615.                 }
  616.                 else
  617.                 {
  618.                     /* search left and right lists */
  619.                     if (((*pepp)->sx+(*pepp)->dx) < cw)
  620.                     {
  621.                         epp = &left_edges[(*pepp)->sx+(*pepp)->dx];
  622.  
  623.                         while (*epp != NULL && (*epp)->sy != (*pepp)->sy)
  624.                             epp = &(*epp)->nextedge;
  625.                     }
  626.                     else
  627.                     {
  628.                         epp = &null_nep;
  629.                     }
  630.  
  631.                     if (*epp == NULL && ((*pepp)->sx+(*pepp)->dx) != 0)
  632.                     {
  633.                         epp = &right_edges[(*pepp)->sx+(*pepp)->dx-1];
  634.                         while (*epp != NULL && (*epp)->sy != (*pepp)->sy)
  635.                             epp = &(*epp)->nextedge;
  636.                     }
  637.                 }
  638.  
  639.                 pepp = &(*pepp)->nextedge;
  640.             } while (*epp != NULL);
  641.  
  642.             ppp = &(*ppp)->nextpoly;
  643.             *pepp = NULL;
  644.         }
  645.     }
  646.  
  647.     /* 3. fill in the slope fields */
  648.     for (pp = firstpoly; pp != NULL; pp = pp->nextpoly)
  649.     {
  650.         epm2 = pp->firstedge;
  651.         epm1 = epm2->nextedge;
  652.         sep = ep = epm1->nextedge;
  653.         epp1 = ep->nextedge;
  654.         epp2 = epp1->nextedge;
  655.         do
  656.         {
  657.             if (epp2 == NULL)
  658.                 epp2 = pp->firstedge;
  659.  
  660.             if (    (epm1->dx ==  1 && epp1->dx ==  1)
  661.                  || (epm1->dx == -1 && epp1->dx == -1) )
  662.             {
  663.                 if (    (ep->dy < 0 && epm2->dy < 0 && epp2->dy < 0)
  664.                      || (ep->dy > 0 && epm2->dy > 0 && epp2->dy > 0) )
  665.                 {
  666.                     if (epm1->dx == 1)
  667.                     {
  668.                         if (ep->dy < 0)
  669.                             ep->slope = SLOPE_NE;
  670.                         else
  671.                             ep->slope = SLOPE_SE;
  672.                     }
  673.                     else
  674.                     {
  675.                         if (ep->dy < 0)
  676.                             ep->slope = SLOPE_NW;
  677.                         else
  678.                             ep->slope = SLOPE_SW;
  679.                     }
  680.                 }
  681.             }
  682.  
  683.             epm2 = epm1;
  684.             epm1 = ep;
  685.             ep = epp1;
  686.             epp1 = epp2;
  687.             epp2 = epp2->nextedge;
  688.         } while (ep != sep);
  689.     }
  690.  
  691.     /* 4. apply slope where necessary */
  692.     for (pp = firstpoly; pp != NULL; pp = pp->nextpoly)
  693.     {
  694.         epm2 = pp->firstedge;
  695.         epm1 = epm2->nextedge;
  696.         sep = ep = epm1->nextedge;
  697.         epp1 = ep->nextedge;
  698.         epp2 = epp1->nextedge;
  699.         do
  700.         {
  701.             if (epp2 == NULL)
  702.                 epp2 = pp->firstedge;
  703.  
  704.             if (ep->dy != 0)
  705.             {
  706.                 if (ep->slope != SLOPE_NONE)
  707.                 {
  708.                     /* edge has a slope that can be applied */
  709.                     edge_smooth(bmp, cw, ch, ep, ep->slope, ep->dy/2);
  710.                 }
  711.                 else if (epm2->slope == SLOPE_NONE && epp2->slope != SLOPE_NONE)
  712.                 {
  713.                     /* apply slope of next edge along */
  714.                     switch(epp2->slope)
  715.                     {
  716.                     case SLOPE_NE:
  717.                     case SLOPE_SW:
  718.                         edge_smooth(bmp, cw, ch, ep, epp2->slope, epp2->dy/2);
  719.                         break;
  720.                     case SLOPE_NW:
  721.                     case SLOPE_SE:
  722.                         edge_smooth(bmp, cw, ch, ep, epp2->slope, ep->dy - (epp2->dy - epp2->dy/2));
  723.                         break;
  724.                     }
  725.                 }
  726.                 else if (epm2->slope != SLOPE_NONE && epp2->slope == SLOPE_NONE)
  727.                 {
  728.                     /* apply slope of previous edge */
  729.                     switch(epm2->slope)
  730.                     {
  731.                     case SLOPE_NW:
  732.                     case SLOPE_SE:
  733.                         edge_smooth(bmp, cw, ch, ep, epm2->slope, epm2->dy/2);
  734.                         break;
  735.                     case SLOPE_NE:
  736.                     case SLOPE_SW:
  737.                         edge_smooth(bmp, cw, ch, ep, epm2->slope, ep->dy - (epm2->dy - epm2->dy/2));
  738.                         break;
  739.                     }
  740.                 }
  741.                 else if (epm2->slope == SLOPE_SW && epp2->slope == SLOPE_SE)
  742.                 {
  743.                     /* concave right edge - apply next and previous edge
  744.                        slopes */
  745.                     edge_smooth(bmp, cw, ch, ep, epm2->slope, ep->dy - (epm2->dy - epm2->dy/2));
  746.                     edge_smooth(bmp, cw, ch, ep, epp2->slope, ep->dy - (epp2->dy - epp2->dy/2));
  747.                 }
  748.                 else if (epm2->slope == SLOPE_NW && epp2->slope == SLOPE_NE)
  749.                 {
  750.                     /* convex left edge - apply next and previous edge
  751.                        slopes */
  752.                     edge_smooth(bmp, cw, ch, ep, epm2->slope, epm2->dy/2);
  753.                     edge_smooth(bmp, cw, ch, ep, epp2->slope, epp2->dy/2);
  754.                 }
  755.             }
  756.  
  757.             epm2 = epm1;
  758.             epm1 = ep;
  759.             ep = epp1;
  760.             epp1 = epp2;
  761.             epp2 = epp2->nextedge;
  762.         } while (ep != sep);
  763.     }
  764.  
  765.     /* 5. sort out adjacent set bits */
  766.     for (y = 0; y < ch; y++)
  767.     {
  768.         for (x = 0; x < cw; x++)
  769.         {
  770.             if (    bitat(sbp, cw, ch, x  , y)
  771.                  && bitat(sbp, cw, ch, x+1, y)
  772.                  && bitat(bmp, cw, ch, x  , y) )
  773.             {
  774.                 /* adjacent pair of bits found */
  775.                 if (bitat(sbp, cw, ch, x+2, y))
  776.                 {
  777.                     /* pair is not at the right edge of character - flip
  778.                        right bit of pair to the right */
  779.                     bitset(bmp, cw, ch, x+1, y);
  780.                 }
  781.                 else if (!bitat(bmp, cw, ch, x+1, y))
  782.                 {
  783.                     /* pair is at the right edge of character */
  784.                     if (bitat(sbp, cw, ch, x-1, y))
  785.                     {
  786.                         /* create two adjacent clear bits in the body
  787.                            of the character */
  788.                         bitclear(sbp, cw, ch, x, y);
  789.                         bitclear(bmp, cw, ch, x, y);
  790.                     }
  791.                     else
  792.                     {
  793.                         /* character is too thin to clear adjacent bits:
  794.                            flip left bit of pair back to the left */
  795.                         bitclear(bmp, cw, ch, x, y);
  796.                     }
  797.                 }
  798.             }
  799.         }
  800.     }
  801.  
  802.     bitmap_free_all(firstpoly, cw, ch);
  803.  
  804.     return(OK);
  805. }
  806.  
  807. /*
  808.  * BITMAP CONVERSION FUNCTIONS
  809.  */
  810.  
  811. int bitmap_compress(sbp, cw, ch, dbp, dsize)
  812. UNSIGNEDBYTE *sbp;  /* pointer to source (normal) bitmap */
  813. UNSIGNEDINT cw, ch; /* dimensions of bitmap in dots */
  814. UNSIGNEDBYTE *dbp;  /* pointer to destination (compressed) bitmap */
  815. UNSIGNEDINT dsize;  /* maximum available space for destination bitmap */
  816. {
  817.     /*
  818.      * Compress a DJ bitmap from normal bitmap format to zero byte
  819.      * compression format. The conversion is done by columns from
  820.      * left to right; within that, by rows from top to bottom. The
  821.      * meaning of the variables is as follows:
  822.      *
  823.      * x, y:    tracks the dot being converted
  824.      * sbp2:    points to the source byte containing the dot being converted
  825.      * smask:   source mask for the dot being converted (used with sbp2)
  826.      * soffset: byte offset between rows of the source bitmap
  827.      * dbp2:    points to the destination data byte containing the dot being converted
  828.      * dmask1:  mask for the destination flag byte (used with dbp)
  829.      * dmask2:  mask for the destination data byte (used with dbp2)
  830.      *
  831.      * The total number of bytes required to encode the output bitmap
  832.      * is returned.
  833.      */
  834.     UNSIGNEDINT x, y, smask;
  835.     UNSIGNEDBYTE *sbp2;
  836.     UNSIGNEDINT dmask1, dmask2, soffset;
  837.     register UNSIGNEDBYTE *dbp2;
  838.  
  839.     /* check sufficient space is available */
  840.     if ((cw + cw*((ch + 7)/8)) > dsize)
  841.         return(ERROR);
  842.  
  843.     dbp2 = dbp + cw;
  844.  
  845.     /* get the byte offset between rows of the source bitmap */
  846.     soffset = (cw + 7)/8;
  847.  
  848.     for (x = 0; x < cw; x++)
  849.     {
  850.         sbp2 = sbp + x/8;
  851.         smask = bits[x%8];
  852.  
  853.         *dbp = 0;
  854.         for (y = 0, dmask1 = 0x01; y < ch; dmask1 <<= 1)
  855.         {
  856.             *dbp2 = 0;
  857.             for (dmask2 = 0x80; y < ch && dmask2 != 0; y++, dmask2 >>= 1)
  858.             {
  859.  
  860.                 if (*sbp2 & smask)
  861.                     *dbp2 |= dmask2;
  862.  
  863.                 sbp2 += soffset;
  864.             }
  865.  
  866.             if (*dbp2 != 0)
  867.             {
  868.                 *dbp |= dmask1;
  869.                 dbp2++;
  870.             }
  871.         }
  872.  
  873.         dbp++;
  874.     }
  875.  
  876.     return((int)(cw + (dbp2 - dbp)));
  877. }
  878.  
  879. int bitmap_decompress(sbp, cw, ch, dbp, dsize)
  880. UNSIGNEDBYTE *sbp;  /* pointer to source (compressed) bitmap */
  881. UNSIGNEDINT cw, ch; /* dimensions of bitmap in dots */
  882. UNSIGNEDBYTE *dbp;  /* pointer to destination (normal) bitmap */
  883. UNSIGNEDINT dsize;  /* maximum available space for destination bitmap */
  884. {
  885.     /*
  886.      * Decompress a DJ bitmap from zero byte compression format to
  887.      * normal bitmap format. This function is the exact reverse of
  888.      * bitmap_compress(). The conversion is done by columns from
  889.      * left to right; within that, by rows from top to bottom. The
  890.      * meaning of the variables is as follows:
  891.      *
  892.      * x, y:    tracks the dot being converted
  893.      * sbp2:    points to the source data byte containing the dot being converted
  894.      * smask1:  mask for the source flag byte (used with sbp)
  895.      * smask2:  mask for the source data byte (used with sbp2)
  896.      * dbp2:    points to the destination byte containing the dot being converted
  897.      * dmask:   destination mask for the dot being converted (used with dbp2)
  898.      * doffset: byte offset between rows of the destination bitmap
  899.      */
  900.     UNSIGNEDINT x, y, smask1, smask2;
  901.     UNSIGNEDBYTE *sbp2 = sbp + cw;
  902.     UNSIGNEDINT dmask, doffset;
  903.     register UNSIGNEDBYTE *dbp2;
  904.  
  905.     /* get the byte offset between rows of the destination bitmap */
  906.     doffset = (cw + 7)/8;
  907.  
  908.     /* check sufficient space is available */
  909.     if ((doffset*ch) > dsize)
  910.         return(ERROR);
  911.  
  912.     for (x = 0; x < cw; x++)
  913.     {
  914.         dbp2 = dbp + x/8;
  915.         dmask = bits[x%8];
  916.  
  917.         for (y = 0, smask1 = 0x01; y < ch; smask1 <<= 1)
  918.         {
  919.             if (smask1 == 0x100)
  920.             {
  921.                 smask1 = 0x01;
  922.                 sbp++;
  923.             }
  924.  
  925.             for (smask2 = 0x80; y < ch && smask2 != 0; y++, smask2 >>= 1)
  926.             {
  927.                 if ((*sbp & smask1) && (*sbp2 & smask2))
  928.                     *dbp2 |= dmask;
  929.                 else
  930.                     *dbp2 &= ~dmask;
  931.  
  932.                 dbp2 += doffset;
  933.             }
  934.  
  935.             if (*sbp & smask1)
  936.                 sbp2++;
  937.         }
  938.  
  939.         sbp++;
  940.     }
  941.  
  942.     return(OK);
  943. }
  944.  
  945. int bitmap_lj_to_dj(sbp, bmp, cw, ch, nl, pl, pr, dbp, dsize)
  946. UNSIGNEDBYTE *sbp;  /* pointer to source (LJ) bitmap */
  947. UNSIGNEDBYTE *bmp;  /* pointer to smoothed bitmap mask */
  948. UNSIGNEDINT cw, ch; /* dimensions of LJ bitmap in dots */
  949. UNSIGNEDINT nl;     /* number of leading blank lines */
  950. UNSIGNEDINT pl;     /* number of pad columns on left */
  951. UNSIGNEDINT pr;     /* number of pad columns on right */
  952. UNSIGNEDBYTE *dbp;  /* pointer to destination (DJ compressed) bitmap */
  953. UNSIGNEDINT dsize;  /* maximum available space for destination bitmap */
  954. {
  955.     /*
  956.      * Convert a bitmap from LJ format to DJ format. This function
  957.      * is similar to bitmap_compress() but does two extra things:
  958.      *
  959.      *   It converts the bitmap from 300x300 resolution to 600x300
  960.      *   resolution by inserting blank bits under the control of the
  961.      *   'bmp' bitmap mask which contains smoothing data.
  962.      *
  963.      *   It adds 'nl' blank lines at the start of the destination
  964.      *   bitmap before moving in the source bitmap. This is useful
  965.      *   because the LJ bitmaps often need to be shifted down in the
  966.      *   DJ bitmap.
  967.      *
  968.      * This routine assumes that ch will less than 64; fortunately this
  969.      * should always be the case since the DJ series cannot handle more
  970.      * than a 50 bit high stripe in a single pass.
  971.      *
  972.      * The meaning of the variables is as follows:
  973.      *
  974.      * x, y:    tracks the dot being converted
  975.      * sbp2:    points to the source byte containing the dot being converted
  976.      * smask:   source mask for the dot being converted (used with sbp2)
  977.      * soffset: byte offset between rows of the source bitmap
  978.      * dbp2:    points to the destination data byte containing the dot being converted
  979.      * dmask1:  mask for the destination flag byte (used with dbp)
  980.      * dmask2:  mask for the destination data byte (used with dbp2)
  981.      *
  982.      * The total number of bytes required to encode the output bitmap
  983.      * is returned.
  984.      */
  985.     UNSIGNEDINT x, y, smask;
  986.     UNSIGNEDBYTE *sbp2;
  987.     UNSIGNEDBYTE *bmp2;
  988.     UNSIGNEDINT dmask1, dmask2, soffset;
  989.     register UNSIGNEDBYTE *dbp2;
  990.  
  991.     /* check sufficient space is available */
  992.     if ((cw*2 + pl + pr + cw*((ch + 7)/8)) > dsize)
  993.         return(ERROR);
  994.  
  995.     dbp2 = dbp + cw*2 + pl + pr;
  996.  
  997.     ch += nl;
  998.     soffset = (cw + 7)/8;
  999.  
  1000.     /* add in blank columns to left of bitmap */
  1001.     for (x = 0; x < pl; x++)
  1002.         *dbp++ = 0;
  1003.  
  1004.     for (x = 0; x < cw; x++)
  1005.     {
  1006.         /* do the left hand column */
  1007.         sbp2 = sbp + x/8;
  1008.         bmp2 = bmp + x/8;
  1009.         smask = bits[x%8];
  1010.  
  1011.         *dbp = 0;
  1012.         for (y = 0, dmask1 = 0x01; y < ch; dmask1 <<= 1)
  1013.         {
  1014.             *dbp2 = 0;
  1015.             for (dmask2 = 0x80; y < ch && dmask2 != 0; y++, dmask2 >>= 1)
  1016.             {
  1017.                 if (y >= nl)
  1018.                 {
  1019.                     if ((*sbp2 ^ *bmp2) & smask)
  1020.                         *dbp2 |= dmask2;
  1021.  
  1022.                     sbp2 += soffset;
  1023.                     bmp2 += soffset;
  1024.                 }
  1025.             }
  1026.  
  1027.             if (*dbp2 != 0)
  1028.             {
  1029.                 *dbp |= dmask1;
  1030.                 dbp2++;
  1031.             }
  1032.         }
  1033.         dbp++;
  1034.  
  1035.         /* do the right hand column */
  1036.         sbp2 = sbp + x/8;
  1037.         bmp2 = bmp + x/8;
  1038.         smask = bits[x%8];
  1039.  
  1040.         *dbp = 0;
  1041.         for (y = 0, dmask1 = 0x01; y < ch; dmask1 <<= 1)
  1042.         {
  1043.             *dbp2 = 0;
  1044.             for (dmask2 = 0x80; y < ch && dmask2 != 0; y++, dmask2 >>= 1)
  1045.             {
  1046.                 if (y >= nl)
  1047.                 {
  1048.                     if ((*sbp2 & *bmp2) & smask)
  1049.                         *dbp2 |= dmask2;
  1050.  
  1051.                     sbp2 += soffset;
  1052.                     bmp2 += soffset;
  1053.                 }
  1054.             }
  1055.  
  1056.             if (*dbp2 != 0)
  1057.             {
  1058.                 *dbp |= dmask1;
  1059.                 dbp2++;
  1060.             }
  1061.         }
  1062.         dbp++;
  1063.     }
  1064.  
  1065.     /* add in blank columns to right of bitmap */
  1066.     for (x = 0; x < pr; x++)
  1067.         *dbp++ = 0;
  1068.  
  1069.     return((int)(cw*2 + pl + pr + (dbp2 - dbp)));
  1070. }
  1071.  
  1072. int bitmap_dj_to_lj(sbp, cw, ch, nl, dbp, dsize)
  1073. UNSIGNEDBYTE *sbp;  /* pointer to source (compressed) bitmap */
  1074. UNSIGNEDINT cw, ch; /* dimensions of bitmap in dots */
  1075. UNSIGNEDINT nl;     /* number of skipped lines */
  1076. UNSIGNEDBYTE *dbp;  /* pointer to destination (normal) bitmap */
  1077. UNSIGNEDINT dsize;  /* maximum available space for destination bitmap */
  1078. {
  1079.     /*
  1080.      * Convert a bitmap from DJ format to LJ format. This function
  1081.      * is similar to bitmap_decompress() but in addition:
  1082.      *
  1083.      *   It converts the bitmap from 600x300 resolution to 300x300
  1084.      *   resolution by ORing together adjacent columns in the DJ
  1085.      *   bitmap.
  1086.      *
  1087.      *   It skips 'nl' blank lines in the destination bitmap before
  1088.      *   starting the conversion.
  1089.      *
  1090.      * x, y:    tracks the dot being converted
  1091.      * sbp2:    points to the source data byte containing the dot being converted
  1092.      * smask1:  mask for the source flag byte (used with sbp)
  1093.      * smask2:  mask for the source data byte (used with sbp2)
  1094.      * dbp2:    points to the destination byte containing the dot being converted
  1095.      * dmask:   destination mask for the dot being converted (used with dbp2)
  1096.      * doffset: byte offset between rows of the destination bitmap
  1097.      */
  1098.     UNSIGNEDINT x, y, smask1, smask2;
  1099.     UNSIGNEDBYTE *sbp2 = sbp + cw;
  1100.     UNSIGNEDINT dmask, doffset;
  1101.     register UNSIGNEDBYTE *dbp2;
  1102.  
  1103.     /* get the byte offset between rows of the destination bitmap */
  1104.     doffset = (cw/2 + 7)/8;
  1105.  
  1106.     /* check sufficient space is available */
  1107.     if ((doffset*(ch + nl)) > dsize)
  1108.         return(ERROR);
  1109.  
  1110.     for (x = 0; x < cw; x++)
  1111.     {
  1112.         dbp2 = dbp + nl*doffset + (x/2)/8;
  1113.         dmask = bits[(x/2)%8];
  1114.  
  1115.         for (y = 0, smask1 = 0x01; y < ch; smask1 <<= 1)
  1116.         {
  1117.             if (smask1 == 0x100)
  1118.             {
  1119.                 smask1 = 0x01;
  1120.                 sbp++;
  1121.             }
  1122.  
  1123.             for (smask2 = 0x80; y < ch && smask2 != 0; y++, smask2 >>= 1)
  1124.             {
  1125.                 if ((*sbp & smask1) && (*sbp2 & smask2))
  1126.                     *dbp2 |= dmask;
  1127.  
  1128.                 dbp2 += doffset;
  1129.             }
  1130.  
  1131.             if (*sbp & smask1)
  1132.                 sbp2++;
  1133.         }
  1134.  
  1135.         sbp++;
  1136.     }
  1137.  
  1138.     return(OK);
  1139. }
  1140.